'''
Coron Lattice Drawer
Author: Victor Codocedo H.
Universintentd Tecnica Federico Santa Maria

Usage:
python coron_drawer.py lats/baclat.lat

baclat.lat is the output of LECO from Coron.
Add names, extension and stability options when executing LECO.
LECO is provided on Coron
'''
from vtk import *
import sys
from lattice_functions import *
from lattice_drawer_functions import *

'''
#####################################################
######## MAIN CODE ##################################
#####################################################
'''
staboffset=0
doClean = True
lattice = ""
if len(sys.argv)<2:
	print "\n*** usage:",sys.argv[0]," [latfile] [stability offset (default=0)]"
	exit()
else:
	lattice = sys.argv[1]
if len(sys.argv) > 2:
	staboffset = float(sys.argv[2])

extent,levels,maxlev,at,den,time = readLattice(lattice)

'''**********************************************************************************
******************* LATTICE CONSTRUCTION ********************************************
*************************************************************************************'''

##################################################################################################
#CLEAN INTENT LATTICE
# This section cleans the intent of the concepts by deleting embedded objects on the concepts.
# i.e. If there are two concepts such as ({A,B,C},{1}) > ({A,B},{1,2}), then the intent for the
# first concept is cleaned leaving it as ({C},{1})
###################################################################################################
if doClean:
	print "Initializing Intent cleaning process...."
	forclean = []
	for e in levels[maxlev]:
		forclean = extent[e]["objects"]
		cleanIntentBottomUp(e,forclean,[],extent)

##################################################################################################
#RECONSTRUCT LATTICE
# This section reconstruct the lattice from the cleaned process. Those concepts with an empty
# intent are removed from the lattice and new connections are created.
# i.e. If there are three concepts int the lattice such as C1 > C2 > C3 and C2 have an empty intent
# the it is deleted and the relation C1 > C3 is created.
###################################################################################################
print "Initializing Lattice Reconstruction...."
todel = {}
for i in range(maxlev):
	todel[i] = []
	for e in levels[i]:
		if len(extent[e]["objects"]) <= 0 or extent[e]["stability"] <= staboffset:
		#if extent[e]["stability"] <= staboffset:
			for c in extent[e]["children"]:
				for p in extent[e]["parents"]:
					if not search(p,c,extent):
						extent[p]["children"].append(c)
						extent[c]["parents"].append(p)
					if e in extent[p]["children"]:
						extent[p]["children"].remove(e)
				if e in extent[c]["parents"]:
					extent[c]["parents"].remove(e)
			del extent[e]
			todel[i].append(e)
for i in todel:
	for e in todel[i]:
		levels[i].remove(e)

##################################################################################################
#CLEAN AMBIGUOUS RELATIONS
# This section cleans relations that add noise in the lattice such as transitive relations.
# i.e. If there are the following relations:
# r1) C1 > C2
# r2) C2 > C3
# r3) C1 > C3
# Then, r3 is deleted since > is transitive and r1 and r2 presupose r3.
###################################################################################################
print "Initializing cleaning..." 
for i in range(maxlev):
	for e in levels[i]:
		for c in extent[e]["children"]:
			del_previous(c,e,extent)
print "Ending cleaning"

sal = writeHierarchy(levels[0][0],extent,maxlev,[])
f=open("hierarchies/"+lattice[lattice.rfind("/"):].replace(".lat","-s"+str(staboffset)+".xml"),"w")
f.write(sal)
f.close()

'''**********************************************************************************
******************* LATTICE VISUALIZATION *******************************************
*************************************************************************************'''

# GRAPH AS DIRECTED
g=vtkMutableDirectedGraph()

# CREATE VERTICES
vertex,points,vertex_id_array,stab_vertex_array,sup_vertex_array,intent_array,size_array = create_lattice_vertices(g,extent,levels,maxlev,staboffset)

# CREATING INVERTED VERTEX INDEX
vertex_inv = {}
for i in vertex:
	vertex_inv[vertex[i]] = i
	
# CREATE EDGES
create_lattice_edges(g,vertex,extent)

# ASSIGN GRAPH DATA TO THE GRAPH
g.GetVertexData().AddArray(stab_vertex_array)
g.GetVertexData().AddArray(sup_vertex_array)
g.GetVertexData().AddArray(vertex_id_array)
g.GetVertexData().AddArray(intent_array)
g.SetPoints(points)

strat = vtkPassThroughLayoutStrategy()
layout = vtk.vtkGraphLayout()
layout.SetInput(g)
layout.SetLayoutStrategy(strat)

# CREATE LAYOUT
view = vtkGraphLayoutView()

# SET THE LABELS FOR EACH NODE
view.SetVertexLabelArrayName("names")
view.SetVertexLabelVisibility(True)
view.SetVertexLabelFontSize(15)

view.SetVertexColorArrayName("stability")
view.SetColorVertices(True)

# Graph-View Binding
view.AddRepresentationFromInputConnection(layout.GetOutputPort())
#view.AddRepresentationFromInput(g)
view.SetLayoutStrategyToPassThrough()

view2 = vtkGraphLayoutView()
drawer = Drawer(extent,maxlev,vertex,vertex_inv,view2)

# Event Configuration
link = vtkSelectionLink()
view.GetRepresentation(0).SetSelectionLink(link)
link.AddObserver("SelectionChangedEvent", drawer.selectionCallback)

# Take selection and extract a graph
extract_graph = vtkExtractSelectedGraph()
extract_graph.AddInputConnection(layout.GetOutputPort())
extract_graph.SetSelectionConnection(link.GetOutputPort())

# Create a view for the extracted graph
#g1 = g

view2.SetVertexLabelArrayName("names")
view2.SetVertexLabelVisibility(True)
view2.SetVertexLabelFontSize(15)
view2.SetVertexColorArrayName("stability")
view2.SetColorVertices(True)
view2.AddRepresentationFromInputConnection(extract_graph.GetOutputPort())
view2.SetLayoutStrategyToPassThrough()
#view2.SetLayoutStrategyToCircular()


#view2.GetRepresentation(0).SetSelectionLink(link)


# VISUALIZATION CONFIGURATION
# Set up the theme
theme = vtkViewTheme.CreateMellowTheme()
theme.SetCellColor(.2,.2,.6)
view.ApplyViewTheme(theme)
view2.ApplyViewTheme(theme)
theme.FastDelete()

updater = vtkViewUpdater()
updater.AddView(view)
updater.AddView(view2)

render = vtkXOpenGLRenderWindow()
inter = vtkXRenderWindowInteractor()
render.SetInteractor(inter)
view.SetupRenderWindow(render)
view.GetRenderWindow().SetSize(600,600)
render.Render()

window2 = vtkRenderWindow()
window2.SetSize(600, 600)
view2.SetupRenderWindow(window2)
view2.GetRenderer().ResetCamera()
view2.GetRenderer().Render()

render.GetInteractor().Start()


# PRINTING SUMMARY
for i in levels:
	print "Cantidad de Conceptos del nivel " + str(i) + ": " + str(len(levels[i]))
